//-------------------------------------------------------------------------------------------------
// Copyright (c) Bradford W. Mott and Flare Contributors
// North Carolina State University, Department of Computer Science
// The IntelliMedia Group
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//-------------------------------------------------------------------------------------------------

using UnityEngine;
using Flare.Display;
using Flare.Geom;

namespace Flare.Text
{
    /// <summary>
    /// TextFormat class provides character and paragraph formatting for TextField objects.
    /// </summary>
    public class TextFormat
    {
        private string m_align;
        private float? m_blockIndent;
        private bool? m_bold;
        private uint? m_color;
        private string m_font;
        private float? m_indent;
        private bool? m_italic;
        private bool? m_float;
        private float? m_leading;
        private float? m_leftMargin;
        private float? m_letterSpacing;
        private float? m_rightMargin;
        private float? m_size;

        /// <summary>
        /// Indicates if the text format object specifies an alignment.
        /// </summary>
        public bool hasAlign
        {
            get { return (this.m_align != null); }
            set { this.m_align = null; }
        }

        /// <summary>
        /// The text alignment.
        /// </summary>
        public string align
        {
            get
            {
                return (this.m_align != null) ? this.m_align : TextFormatAlign.LEFT;
            }
            set
            {
                if (TextFormatAlign.IsMember(value))
                {
                    this.m_align = value;
                }
                else
                {
                    throw new global::System.ArgumentException("Specified alignment not valid.");
                }
            }
        }

        /// <summary>
        /// Indicates if the text format object specifies a block indent.
        /// </summary>
        public bool hasBlockIndent
        {
            get { return this.m_blockIndent.HasValue; }
            set { this.m_blockIndent = null; }
        }

        /// <summary>
        /// The block indent.
        /// </summary>
        public float blockIndent
        {
            get { return (this.m_blockIndent.HasValue) ? this.m_blockIndent.Value : 0.0f; }
            set { this.m_blockIndent = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies text should be bold.
        /// </summary>
        public bool hasBold
        {
            get { return this.m_bold.HasValue; }
            set { this.m_bold = null; }
        }

        /// <summary>
        /// The bold setting for the text.
        /// </summary>
        public bool bold
        {
            get { return (this.m_bold.HasValue) ? this.m_bold.Value : false; }
            set { this.m_bold = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies a text color.
        /// </summary>
        public bool hasColor
        {
            get { return this.m_color.HasValue; }
            set { this.m_color = null; }
        }

        /// <summary>
        /// The color of the text as an RGB hexadecimal value.
        /// </summary>
        public uint color
        {
            get { return (this.m_color.HasValue) ? this.m_color.Value : 0x000000; }
            set { this.m_color = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies a font.
        /// </summary>
        public bool hasFont
        {
            get { return (this.m_font != null); }
            set { this.m_font = null; }
        }

        /// <summary>
        /// The text font.
        /// </summary>
        public string font
        {
            get { return (this.m_font != null) ? this.m_font : "Times New Roman"; }
            set { this.m_font = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies an indent.
        /// </summary>
        public bool hasIndent
        {
            get { return this.m_indent.HasValue; }
            set { this.m_indent = null; }
        }

        /// <summary>
        /// The text indent.
        /// </summary>
        public float indent
        {
            get { return (this.m_indent.HasValue) ? this.m_indent.Value : 0.0f; }
            set { this.m_indent = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies the text should be italic.
        /// </summary>
        public bool hasItalic
        {
            get { return this.m_italic.HasValue; }
            set { this.m_italic = null; }
        }

        /// <summary>
        /// The italic setting for the text.
        /// </summary>
        public bool italic
        {
            get { return (this.m_italic.HasValue) ? this.m_italic.Value : false; }
            set { this.m_italic = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies a leading.
        /// </summary>
        public bool hasLeading
        {
            get { return this.m_leading.HasValue; }
            set { this.m_leading = null; }
        }

        /// <summary>
        /// The leading.
        /// </summary>
        public float leading
        {
            get { return (this.m_leading.HasValue) ? this.m_leading.Value : 0.0f; }
            set { this.m_leading = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies a left margin.
        /// </summary>
        public bool hasLeftMargin
        {
            get { return this.m_leftMargin.HasValue; }
            set { this.m_leftMargin = null; }
        }

        /// <summary>
        /// The left margin.
        /// </summary>
        public float leftMargin
        {
            get { return (this.m_leftMargin.HasValue) ? this.m_leftMargin.Value : 0.0f; }
            set { this.m_leftMargin = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies a letter spacing.
        /// </summary>
        public bool hasLetterSpacing
        {
            get { return this.m_letterSpacing.HasValue; }
            set { this.m_letterSpacing = null; }
        }

        /// <summary>
        /// The letter spacing.
        /// </summary>
        public float letterSpacing
        {
            get { return (this.m_letterSpacing.HasValue) ? this.m_letterSpacing.Value : 0.0f; }
            set { this.m_letterSpacing = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies a right margin.
        /// </summary>
        public bool hasRightMargin
        {
            get { return this.m_rightMargin.HasValue; }
            set { this.m_rightMargin = null; }
        }

        /// <summary>
        /// The right margin.
        /// </summary>
        public float rightMargin
        {
            get { return (this.m_rightMargin.HasValue) ? this.m_rightMargin.Value : 0.0f; }
            set { this.m_rightMargin = value; }
        }

        /// <summary>
        /// Indicates if the text format object specifies a text size.
        /// </summary>
        public bool hasSize
        {
            get { return this.m_size.HasValue; }
            set { this.m_size = null; }
        }

        /// <summary>
        /// The text size.
        /// </summary>
        public float size
        {
            get { return (this.m_size.HasValue) ? this.m_size.Value : 12.0f; }
            set { this.m_size = value; }
        }

        /// <summary>
        /// Initializes a new instance of the TextFormat class.
        /// </summary>
        public TextFormat(string font = null, float? size = null, uint? color = null,
            bool? bold = null, bool? italic = null, string align = null,
            float? leftMargin = null, float? rightMargin = null, float? indent = null,
            float? leading = null)
        {
            this.m_font = font;
            this.m_size = size;
            this.m_color = color;
            this.m_bold = bold;
            this.m_italic = italic;
            this.m_align = align;
            this.m_leftMargin = leftMargin;
            this.m_rightMargin = rightMargin;
            this.m_indent = indent;
            this.m_leading = leading;
        }

        /// <summary>
        /// Initializes a new instance of the TextFormat class.
        /// </summary>
        public TextFormat(TextFormat obj)
        {
            this.m_align = obj.m_align;
            this.m_blockIndent = obj.m_blockIndent;
            this.m_bold = obj.m_bold;
            this.m_color = obj.m_color;
            this.m_font = obj.m_font;
            this.m_indent = obj.m_indent;
            this.m_italic = obj.m_italic;
            this.m_leading = obj.m_leading;
            this.m_leftMargin = obj.m_leftMargin;
            this.m_letterSpacing = obj.m_letterSpacing;
            this.m_rightMargin = obj.m_rightMargin;
            this.m_size = obj.m_size;
        }

        public override string ToString()
        {
            return string.Format("(font={0}, size={1}, color=0x{2:X}, bold={3}, italic={4}, " +
                "align={5}, leftMargin={6}, rightMargin={7}, indent={8}, leading={9}, " +
                "blockIndent={10} letterSpacing={11})",
                this.m_font, this.m_size, this.m_color, this.m_bold, this.m_italic, this.m_align,
                this.m_leftMargin, this.m_rightMargin, this.m_indent, this.m_leading,
                this.m_blockIndent, this.m_letterSpacing);
        }
    }
}